Title: x86assembly - ch5 - procedures & stack - book notes

A stack data structure follows the same principle as a stack of plates: New values are added to the top of the stack, and existing values are removed from the top.
Extra: link: wikipedia 'call stack'
url: https://en.wikipedia.org/wiki/Call_stack
Topic: procedures

The runtime stack is a memory array managed directly by the CPU, using the ESP (extended stack pointer) register.
In 32-bit mode, the ESP register holds a 32-bit offset into some location on the stack.
ESP always points to the last value to be added, or pushed on the top of the stack.
The ESP is manipulated with instructions such as CALL, RET, PUSH, and POP.
Extra: link to c-jump.com
url: http://www.c-jump.com/CIS77/ASM/Stack/S77_0040_esp_register.htm
Topic: stack

Q: The 32 bit [...] instruction decrements the stack pointer ([...] register) by [...] and copies a value into the location in the stack pointed to by the stack pointer.
A: push; ESP; 4
url: http://www.c-jump.com/CIS77/ASM/Stack/S77_0040_esp_register.htm
Topic: stack

Q: A [...] instruction removes a value from the stack. After a value is removed, the stack pointer is [...] by the stack element size to point to the next highest location in the stack.
The area of the stack below where the [...] register points is logically empty, and will be overwritten the next time a value is pushed to the stack.
A: pop; incremented; ESP
url: http://www.c-jump.com/CIS77/ASM/Stack/S77_0040_esp_register.htm
Topic: stack

The runtime stack is commonly used to:
- be a convenient temporary save area for registers when they are used for more than one purpose. They can be restored to their original values from data stored on the stack.
- saving a subroutines return address when a CALL instruction executes
- passing arguments to a subroutine by pushing them on the stack
- temporary storage for local variables inside subroutines
url: http://www.c-jump.com/CIS77/ASM/Stack/S77_0040_esp_register.htm

The PUSH instruction decrements and the POP instruction increments the stack pointer. The amount they are incremented by depends on the size of the operand. A 16-bit operand moves the pointer by 2 while a 32-bit operand moves it by 4.
1
2
3
4
PUSH eax ; move by 4
PUSH ax   ; move by 2
POP eax    ; move by 4
POP ax     ; move by 2
Operands can be registers, memory, or immediate
url: http://www.c-jump.com/CIS77/ASM/Stack/S77_0040_esp_register.htm
Topic: stack

The PUSHFD instruction pushes the 32-bit EFLAGS register on the stack and POPFD pops the top value in the stack into EFLAGS. Neither instruction takes operands.
Extra: link to pushfd
url: https://www.felixcloutier.com/x86/pushf:pushfd:pushfq
Topic: stack

The PUSHAD instruction pushes all the 32-bit general purpose registers on the stack in this order:
1. eax
2. ecx
3. edx
4. ebx
5. esp (value before pushad)
6. ebp
7. esi
8. edi
The pusha instruction uses the same order, but pushes the 16-bit lowers of those registers instead. It should only be used in 16-bit mode.
POPAD and POPA pop the stack back to registers in reverse order.
Extra: link to felix cloutier pushad info page
url: https://www.felixcloutier.com/x86/pusha:pushad
Topic: stack

The PROC directive defines a procedure and the ENDP directive ends the procedure block. It must have a RET instruction to end it.
1
2
3
4
my_proc proc
; code
ret
my_proc endp
Extra: fc , ret insturction info
url: https://www.felixcloutier.com/x86/ret
Topic: stack

Labels within procedures are visible only within the procedure, relevant for jump and loop instructions.
A global label can be declared with a double-colon ( after its name, but using global labels is often bad practice.
Topic: stack

Q: A good habit for documenting procedures is to list the following:
- description of tasks accomplished by procedure
- list of input parameters and their usage, labeled by a word [...]
- description of any values returned by the procedure, labeled by [...]
- A list of special requirements, called Preconditions, that must be satisfied before the procedure is called. Labeled by [...]
A: Receives; Returns; Requires
Extra: 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
;---------------------------------------------------------
    ; sumof
    ;
    ; Calculates and returns the sum of three 32-bit integers.
    ; Receives: EAX, EBX, ECX, the three integers. May be
    ;           signed or unsigned.
    ; Returns:  EAX = sum
    SumOf PROC
        add  eax,ebx
        add  eax,ecx
        ret
    SumOf ENDP
Topic: procedures

The call instruction calls a procedure by the directing the processor to begin execution at a new memory location, generally referenced by the procedure's identifier. The procedure uses the ret instruction to bring the processor back to the point in the program where the procedure was called.
Mechanically, the call instruction pushes its return address on the stack and copies the called procedure's address into the instruction pointer. When the procedure returns, RET pops the return address from the stack into the instruction pointer.
Reminder: In 32-bit mode, the CPU executes instruction in memory pointed to by the EIP register.
Extra: fc call info
url: https://www.felixcloutier.com/x86/call
Topic: stack

Q: A [...] procedure call occurs when a called procedure calls another procedure before the first procedure returns.
A: nested

Q: Passing [...] to procedures is generally accomplished by moving values to [...] prior to calling the procedure, which the procedure then references.
A: parameters; registers
Extra: Array sum example:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
; ArraySum
    ;
    ; Calculates the sum of an array of 32-bit integers.
    ; Receives: ESI = the array offset
    ;           ECX = number of elements in the array
    ; Returns:  EAX = sum of the array elements
    ;
    ArraySum PROC
         push  esi                 ; save ESI, ECX
         push  ecx
         mov   eax,0               ; set the sum to zero
    L1:  add   eax,[esi]           ; add each integer to sum
         add   esi,TYPE DWORD      ; point to next integer
         loop L1                   ; repeat for array size
         pop  ecx                  ; restore ECX, ESI
         pop  esi
         ret                       ; sum is in EAX
    ArraySum ENDP

When using registers to pass parameters, the parameter registers are pushed onto the stack at the beginning of the procedure and popped at the end. It is good practice to always save and restore registers that are modified by a procedure this way so the calling program can be sure none of its own registers will be overwritten.
The exeption is registers used as return values, which is typically the EAX register; they should not be popped and pushed.
Extra: 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
; Testing the ArraySum procedure (TestArraySum.asm)
    .386
    .model flat, stdcall
    .stack 4096
    ExitProcess PROTO, dwExitCode:DWORD
    .data
    array DWORD 10000h,20000h,30000h,40000h,50000h
    theSum DWORD ?
    .code
    main PROC
         mov   esi,OFFSET array    ; ESI points to array
         mov   ecx,LENGTHOF array  ; ECX = array count
         call  ArraySum            ; calculate the sum
         mov   theSum,eax          ; returned in EAX
         INVOKE ExitProcess,0 main ENDP
    ;
    ; ArraySum
    ; Calculates the sum of an array of 32-bit integers.
    ; Receives: ESI = the array offset
    ; ECX = number of elements in the array
    ; Returns: EAX = sum of the array elements
    ;
    ArraySum PROC
        push  esi                 ; save ESI, ECX
        push  ecx
        mov   eax,0               ; set the sum to zero
    L1:
        add   eax,[esi]           ; add each integer to sum
        add   esi,TYPE DWORD      ; point to next integer
        loop  L1                  ; repeat for array size
        pop   ecx                 ; restore ECX, ESI
        pop   esi
        ret                       ; sum is in EAX
    ArraySum ENDP
    END main
Topic: stack

The USES operator with the PROC directive allows listing the names of all registers modified within a procedure.
USES tells the assembler to do two things:
1. Generate PUSH instructions that save the registers on the stack at the beginning of the procedure.
2. Generate POP instructions that restore the register values at the end of the procedure.
So you can write fewer instructions using this.
Extra: Example of USES:
1
2
3
4
5
6
7
8
ArraySum PROC USES esi ecx
         mov  eax,0                ; set the sum to zero
    L1:
         add  eax,[esi]            ; add each integer to sum
         add  esi,TYPE DWORD       ; point to next integer
         loop  L1                  ; repeat for array size
         ret                       ; sum is in EAX
    ArraySum ENDP
The assembler will generate the following code from the above, adding push and pops:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
ArraySum PROC
         push esi
         push ecx
         mov  eax,0                ; set the sum to zero
    L1:
         add  eax,[esi]            ; add each integer to sum
         add  esi,TYPE DWORD       ; point to next integer
         loop L1                   ; repeat for array size
         pop  ecx
         pop  esi
         ret
    ArraySum ENDP
Topic: stack